package service

import (
	"context"
	"database/sql"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"miaoyuadmin/internal/dao"
	"miaoyuadmin/internal/enums/roleenum"
	"miaoyuadmin/internal/model"
	"miaoyuadmin/internal/model/entity"
)

type roleService struct {
}

var roleS = roleService{}

func Role() *roleService {
	return &roleS
}

//GetRoleListJoinTag 获取所有角色列表包括当前用户标志
func (s *roleService) GetRoleListJoinTag(ctx context.Context, userId int) (res []model.RoleWithTagOutput, resErr error) {
	roleList, err := s.GetAllList(ctx, nil)
	if err != nil {
		resErr = err
		g.Log().Print(ctx, "获取角色列表信息失败", err)
		return
	}
	roleLength := len(roleList)
	res = make([]model.RoleWithTagOutput, roleLength)

	userRoleList, err := dao.MyUserRole.GetRoleListByUserId(ctx, userId)
	if err != nil {
		resErr = err
		g.Log().Print(ctx, "获取角色列表信息失败", err)
		return
	}
	for k, v := range roleList {
		res[k].Title = v.Title
		res[k].Id = v.Id
		res[k].CodeName = v.CodeName
		res[k].Bak = v.Bak
		if v.Status == gconv.Int(roleenum.Enable) {
			res[k].IsEnable = true
		} else {
			res[k].IsEnable = false
		}
		res[k].IsCheck = false
		for _, vv := range userRoleList {
			if v.Id == vv {
				res[k].IsCheck = true
			}
		}
	}

	return
}

//GetRoleListByUserId 获取所有角色列表
func (s *roleService) GetRoleListByUserId(ctx context.Context, userId int) (res []int, resErr error) {

	roleList, err := dao.MyUserRole.GetRoleListByUserId(ctx, userId)
	if err != nil {
		resErr = err
		g.Log().Print(ctx, "获取角色列表信息失败", err)
		return
	}
	res = roleList
	return
}

//GetAllList 获取所有角色列表
func (s *roleService) GetAllList(ctx context.Context, where g.MapStrAny) (res []entity.MyRole, resErr error) {

	res, resErr = dao.MyRole.GetAllList(ctx, where)

	return
}

//GetAllEnableList 获取所有角色列表
func (s *roleService) GetAllEnableList(ctx context.Context, where g.MapStrAny) (res []entity.MyRole, resErr error) {
	if where != nil {
		where["status"] = roleenum.Enable
	} else {
		where = g.MapStrAny{"status": roleenum.Enable}
	}
	res, resErr = dao.MyRole.GetAllList(ctx, where)

	return
}
func (s *roleService) GetPageList(ctx context.Context, options model.RoleListInput) (list []model.RoleOutput, count int, err error) {
	var condition g.MapStrAny
	var pageLimit model.PageLimit
	if options.Keywords != "" {
		condition = make(g.MapStrAny)
		condition["title like ?"] = "%" + options.Keywords + "%"
	}
	pageLimit.Start = (options.Page - 1) * options.Limit
	pageLimit.Limit = options.Limit

	resList, resCount, resErr := dao.MyRole.GetPageList(ctx, condition, pageLimit)

	if resErr != nil {
		err = resErr
		return
	}
	count = resCount

	scanErr := gconv.Scan(resList, &list)
	if scanErr != nil {
		err = gerror.New("获取数据错误")
		return
	}

	return
}
func (s *roleService) checkSubmit(ctx context.Context, data model.RoleSubmitInput) (err error) {
	//检查是否有重复的角色编码
	_, resErr := dao.MyRole.GetItem(ctx, g.MapStrAny{"code_name": data.CodeName})
	if resErr != nil && resErr != sql.ErrNoRows {
		err = gerror.New("数据获取错误")
		return
	}
	if resErr != sql.ErrNoRows {
		err = gerror.New("角色编码已存在")
		return
	}

	return
}
func (s *roleService) GetItemById(ctx context.Context, id int) (res entity.MyRole, resErr error) {
	res, resErr = dao.MyRole.GetItemById(ctx, id)
	if resErr != nil && resErr != sql.ErrNoRows {
		resErr = gerror.New("检索错误")
		return
	}
	if resErr == sql.ErrNoRows {
		resErr = gerror.NewSkip(404, "数据不存在")
		return
	}
	return
}
func (s *roleService) Grant(ctx context.Context, id int, menus []int) (res sql.Result, err error) {
	menuLength := len(menus)
	grantList := make([]entity.MyRoleMenu, menuLength)

	for key, ele := range menus {
		grantList[key] = entity.MyRoleMenu{RoleId: id, MenuId: ele}
	}
	_, delErr := dao.MyRoleMenu.DeleteItemById(ctx, id)
	if delErr != nil {
		err = delErr
		return
	}
	res, err = dao.MyRoleMenu.GrantMenuToRole(ctx, grantList)

	if err != nil {
		return
	}
	//更新casbin策略库

	Access().UpdateRolePolicy(ctx, id, menus)

	return
}
func (s *roleService) Add(ctx context.Context, options model.RoleSubmitInput) (res sql.Result, err error) {
	checkErr := s.checkSubmit(ctx, options)
	if checkErr != nil {
		err = checkErr
		return
	}
	res, err = dao.MyRole.Add(ctx, options)
	if err != nil {

		return
	}
	return
}
func (s *roleService) Edit(ctx context.Context, options model.RoleSubmitInput, resId int) (res sql.Result, err error) {
	res, err = dao.MyRole.UpdateItemById(ctx, options, resId)

	if err != nil {
		return
	}

	return
}

func (s *roleService) Del(ctx context.Context, resId int) (sqlAffectRows int64, err error) {

	sqlAffectRows, err = dao.MyRole.DeleteItemById(ctx, resId)
	if err != nil {
		err = gerror.NewSkip(404, "角色删除失败")
		return
	}
	if sqlAffectRows == 0 {
		err = gerror.New("请求的信息不存在")
		return
	}

	return
}
